page.tsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. "use client";
  2. import {fetchApi, fetchFile} from "@/app/_modules/func";
  3. import {DeleteOutlined, ExclamationCircleFilled, PlusOutlined, ReloadOutlined,} from "@ant-design/icons";
  4. import type {ActionType, ProColumns, ProFormInstance,} from "@ant-design/pro-components";
  5. import {
  6. ModalForm,
  7. PageContainer,
  8. ProForm,
  9. ProFormDigit,
  10. ProFormRadio,
  11. ProFormSelect,
  12. ProFormText,
  13. ProFormTextArea,
  14. ProTable,
  15. } from "@ant-design/pro-components";
  16. import {Button, Modal, Space, Tag} from "antd";
  17. import {useRouter} from "next/navigation";
  18. import {faCheck, faDownload, faPenToSquare, faToggleOff, faToggleOn, faXmark,} from "@fortawesome/free-solid-svg-icons";
  19. import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
  20. import {useRef, useState} from "react";
  21. //查询类型详情
  22. const queryTypeAPI = "/api/system/dict/type";
  23. //查询所有类型列表
  24. const queryTypeListAPI = "/api/system/dict/type/optionselect";
  25. //查询表格数据API
  26. const queryAPI = "/api/system/dict/data/list";
  27. //新建数据API
  28. const newAPI = "/api/system/dict/data";
  29. //修改数据API
  30. const modifyAPI = "/api/system/dict/data";
  31. //查询详情数据API
  32. const queryDetailAPI = "/api/system/dict/data";
  33. //删除API
  34. const deleteAPI = "/api/system/dict/data";
  35. //导出API
  36. const exportAPI = "/api/system/dict/data/export";
  37. //导出文件前缀名
  38. const exportFilePrefix = "data";
  39. export default function DictData({ params }: { params: { dictid: string } }) {
  40. const { push } = useRouter();
  41. // 添加用于控制删除确认模态框的状态
  42. const [deleteModalVisible, setDeleteModalVisible] = useState(false);
  43. const [deleteDictCode, setDeleteDictCode] = useState<string | number | null>(null);
  44. const [defaultType, setDefaultType] = useState("");
  45. //获取对应的字典类型的值
  46. const getTypeData = async () => {
  47. const resp = await fetchApi(`${queryTypeAPI}/${params.dictid}`, push);
  48. if (resp != undefined) {
  49. if (searchTableFormRef.current) {
  50. searchTableFormRef.current.setFieldsValue({
  51. dictType: resp.data.dictType,
  52. });
  53. }
  54. setDefaultType(resp.data.dictType);
  55. return resp.data.dictType;
  56. }
  57. return "";
  58. };
  59. //查询字典类型列表
  60. const getTypeList = async () => {
  61. const dataArray: Array<any> = new Array<any>();
  62. const resp = await fetchApi(queryTypeListAPI, push);
  63. if (resp != undefined) {
  64. resp.data.forEach((item: any) => {
  65. const type = {
  66. label: item.dictName,
  67. value: item.dictType,
  68. };
  69. dataArray.push(type);
  70. });
  71. }
  72. return dataArray;
  73. };
  74. //表格列定义
  75. const columns: ProColumns[] = [
  76. {
  77. title: "字典名称",
  78. dataIndex: "dictType",
  79. valueType: "select",
  80. fieldProps: {
  81. allowClear: false,
  82. },
  83. request: getTypeList,
  84. hideInTable: true,
  85. order: 3,
  86. },
  87. {
  88. title: "数据编码",
  89. dataIndex: "dictCode",
  90. search: false,
  91. },
  92. {
  93. title: "数据标签",
  94. fieldProps: {
  95. placeholder: "请输入数据标签",
  96. },
  97. dataIndex: "dictLabel",
  98. order: 2,
  99. render: (_, record) => {
  100. const isTag = record.listClass === "";
  101. let tagColor = "default";
  102. if (record.listClass === "") {
  103. return _;
  104. } else {
  105. switch (record.listClass) {
  106. case "default":
  107. tagColor = "processing";
  108. break;
  109. case "primary":
  110. tagColor = "processing";
  111. break;
  112. case "success":
  113. tagColor = "success";
  114. break;
  115. case "info":
  116. tagColor = "default";
  117. break;
  118. case "warning":
  119. tagColor = "warning";
  120. break;
  121. case "danger":
  122. tagColor = "error";
  123. break;
  124. default:
  125. tagColor = "processing";
  126. break;
  127. }
  128. return (
  129. <Space>
  130. <Tag color={tagColor}>{_}</Tag>
  131. </Space>
  132. );
  133. }
  134. },
  135. },
  136. {
  137. title: "数据键值",
  138. dataIndex: "dictValue",
  139. search: false,
  140. },
  141. {
  142. title: "数据排序",
  143. dataIndex: "dictSort",
  144. sorter: true,
  145. search: false,
  146. },
  147. {
  148. title: "状态",
  149. fieldProps: {
  150. placeholder: "请选择数据状态",
  151. },
  152. dataIndex: "status",
  153. valueType: "select",
  154. render: (_, record) => {
  155. return (
  156. <Space>
  157. <Tag
  158. color={record.status === "0" ? "green" : "red"}
  159. icon={
  160. record.status == 0 ? (
  161. <FontAwesomeIcon icon={faCheck} />
  162. ) : (
  163. <FontAwesomeIcon icon={faXmark} />
  164. )
  165. }
  166. >
  167. {_}
  168. </Tag>
  169. </Space>
  170. );
  171. },
  172. valueEnum: {
  173. 0: {
  174. text: "正常",
  175. status: "0",
  176. },
  177. 1: {
  178. text: "停用",
  179. status: "1",
  180. },
  181. },
  182. order: 1,
  183. },
  184. {
  185. title: "备注",
  186. dataIndex: "remark",
  187. search: false,
  188. },
  189. {
  190. title: "创建时间",
  191. dataIndex: "createTime",
  192. valueType: "dateTime",
  193. search: false,
  194. },
  195. {
  196. title: "操作",
  197. key: "option",
  198. search: false,
  199. render: (_, record) => [
  200. <Button
  201. key="modifyBtn"
  202. type="link"
  203. icon={<FontAwesomeIcon icon={faPenToSquare} />}
  204. onClick={() => onClickShowRowModifyModal(record)}
  205. >
  206. 修改
  207. </Button>,
  208. <Button
  209. key="deleteBtn"
  210. type="link"
  211. danger
  212. icon={<DeleteOutlined />}
  213. onClick={() => onClickDeleteRow(record)}
  214. >
  215. 删除
  216. </Button>,
  217. ],
  218. },
  219. ];
  220. //0.查询表格数据
  221. const queryTableData = async (params: any, sorter: any, filter: any) => {
  222. const searchParams = {
  223. pageNum: params.current,
  224. ...params,
  225. };
  226. delete searchParams.current;
  227. const queryParams = new URLSearchParams(searchParams);
  228. //如果没有带上默认的字典类型,查询绑定上
  229. if (!("dictType" in searchParams)) {
  230. const defaultType = await getTypeData();
  231. queryParams.append("dictType", defaultType);
  232. }
  233. Object.keys(sorter).forEach((key) => {
  234. queryParams.append("orderByColumn", key);
  235. if (sorter[key] === "ascend") {
  236. queryParams.append("isAsc", "ascending");
  237. } else {
  238. queryParams.append("isAsc", "descending");
  239. }
  240. });
  241. const body = await fetchApi(`${queryAPI}?${queryParams}`, push);
  242. return body;
  243. };
  244. //1.新建
  245. //确定新建数据
  246. const executeAddData = async (values: any) => {
  247. const body = await fetchApi(newAPI, push, {
  248. method: "POST",
  249. headers: {
  250. "Content-Type": "application/json",
  251. },
  252. body: JSON.stringify(values),
  253. });
  254. if (body != undefined) {
  255. if (body.code == 200) {
  256. App.useApp().message.success(body.msg);
  257. if (actionTableRef.current) {
  258. actionTableRef.current.reload();
  259. }
  260. return true;
  261. }
  262. App.useApp().message.error(body.msg);
  263. return false;
  264. }
  265. return false;
  266. };
  267. //2.修改
  268. //是否展示修改对话框
  269. const [isShowModifyDataModal, setIsShowModifyDataModal] = useState(false);
  270. //展示修改对话框
  271. const onClickShowRowModifyModal = (record?: any) => {
  272. queryRowData(record);
  273. setIsShowModifyDataModal(true);
  274. };
  275. //修改数据表单引用
  276. const modifyFormRef = useRef<ProFormInstance>(null);
  277. //操作当前数据的附加数据
  278. const [operatRowData, setOperateRowData] = useState<{
  279. [key: string]: any;
  280. }>({});
  281. //查询并加载待修改数据的详细信息
  282. const queryRowData = async (record?: any) => {
  283. const dictCode =
  284. record !== undefined ? record.dictCode : selectedRow.dictCode;
  285. operatRowData["dictCode"] = dictCode;
  286. setOperateRowData(operatRowData);
  287. if (dictCode !== undefined) {
  288. const body = await fetchApi(`${queryDetailAPI}/${dictCode}`, push);
  289. if (body !== undefined) {
  290. if (body.code == 200) {
  291. modifyFormRef?.current?.setFieldsValue({
  292. //需要加载到修改表单中的数据
  293. dictType: body.data.dictType,
  294. dictLabel: body.data.dictLabel,
  295. dictValue: body.data.dictValue,
  296. dictSort: body.data.dictSort,
  297. status: body.data.status,
  298. listClass: body.data.listClass,
  299. cssClass: body.data.cssClass,
  300. remark: body.data.remark,
  301. });
  302. }
  303. }
  304. }
  305. };
  306. //确认修改数据
  307. const executeModifyData = async (values: any) => {
  308. values["dictCode"] = operatRowData["dictCode"];
  309. const body = await fetchApi(modifyAPI, push, {
  310. method: "PUT",
  311. headers: {
  312. "Content-Type": "application/json",
  313. },
  314. body: JSON.stringify(values),
  315. });
  316. if (body !== undefined) {
  317. if (body.code == 200) {
  318. App.useApp().message.success(body.msg);
  319. //刷新列表
  320. if (actionTableRef.current) {
  321. actionTableRef.current.reload();
  322. }
  323. setIsShowModifyDataModal(false);
  324. return true;
  325. }
  326. App.useApp().message.error(body.msg);
  327. return false;
  328. }
  329. };
  330. //3.删除
  331. //点击删除按钮,展示删除确认框
  332. const onClickDeleteRow = (record?: any) => {
  333. const dictCode = record !== undefined ? record.dictCode : selectedRowKeys.join(",");
  334. setDeleteDictCode(dictCode);
  335. setDeleteModalVisible(true);
  336. };
  337. //确定删除选中的数据
  338. const executeDeleteRow = async () => {
  339. if (deleteDictCode === null) return;
  340. const body = await fetchApi(`${deleteAPI}/${deleteDictCode}`, push, {
  341. method: "DELETE",
  342. });
  343. if (body !== undefined) {
  344. if (body.code == 200) {
  345. App.useApp().message.success("删除成功");
  346. //修改按钮变回不可点击
  347. setRowCanModify(false);
  348. //删除按钮变回不可点击
  349. setRowCanDelete(false);
  350. //选中行数据重置为空
  351. setSelectedRowKeys([]);
  352. //刷新列表
  353. if (actionTableRef.current) {
  354. actionTableRef.current.reload();
  355. }
  356. } else {
  357. App.useApp().message.error(body.msg);
  358. }
  359. }
  360. setDeleteModalVisible(false);
  361. setDeleteDictCode(null);
  362. };
  363. //4.导出
  364. //导出表格数据
  365. const exportTable = async () => {
  366. if (searchTableFormRef.current) {
  367. const formData = new FormData();
  368. const data = {
  369. pageNum: page,
  370. pageSize: pageSize,
  371. ...searchTableFormRef.current.getFieldsValue(),
  372. };
  373. Object.keys(data).forEach((key) => {
  374. if (data[key] !== undefined) {
  375. formData.append(key, data[key]);
  376. }
  377. });
  378. await fetchFile(
  379. exportAPI,
  380. push,
  381. {
  382. method: "POST",
  383. body: formData,
  384. },
  385. `${exportFilePrefix}_${new Date().getTime()}.xlsx`
  386. );
  387. }
  388. };
  389. //5.选择行
  390. //选中行操作
  391. const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  392. const [selectedRow, setSelectedRow] = useState(undefined as any);
  393. //修改按钮是否可用,选中行时才可用
  394. const [rowCanModify, setRowCanModify] = useState(false);
  395. //删除按钮是否可用,选中行时才可用
  396. const [rowCanDelete, setRowCanDelete] = useState(false);
  397. //ProTable rowSelection
  398. const rowSelection = {
  399. onChange: (newSelectedRowKeys: React.Key[], selectedRows: any[]) => {
  400. setSelectedRowKeys(newSelectedRowKeys);
  401. setRowCanDelete(newSelectedRowKeys && newSelectedRowKeys.length > 0);
  402. if (newSelectedRowKeys && newSelectedRowKeys.length == 1) {
  403. setSelectedRow(selectedRows[0]);
  404. setRowCanModify(true);
  405. } else {
  406. setRowCanModify(false);
  407. setSelectedRow(undefined);
  408. }
  409. },
  410. //复选框的额外禁用判断
  411. // getCheckboxProps: (record) => ({
  412. // disabled: record.userId == 1,
  413. // }),
  414. };
  415. //搜索栏显示状态
  416. const [showSearch, setShowSearch] = useState(true);
  417. //action对象引用
  418. const actionTableRef = useRef<ActionType>(null);
  419. //搜索表单对象引用
  420. const searchTableFormRef = useRef<ProFormInstance>(null!);
  421. //当前页数和每页条数
  422. const [page, setPage] = useState(1);
  423. const defaultPageSize = 10;
  424. const [pageSize, setPageSize] = useState(defaultPageSize);
  425. const pageChange = (page: number, pageSize: number) => {
  426. setPage(page);
  427. setPageSize(pageSize);
  428. };
  429. return (
  430. <PageContainer
  431. header={{
  432. title: "字典数据",
  433. onBack(e) {
  434. push("/system/dict");
  435. },
  436. }}
  437. >
  438. <ProTable
  439. formRef={searchTableFormRef}
  440. rowKey="dictCode"
  441. rowSelection={{
  442. selectedRowKeys,
  443. ...rowSelection,
  444. }}
  445. columns={columns}
  446. request={async (params: any, sorter: any, filter: any) => {
  447. // 表单搜索项会从 params 传入,传递给后端接口。
  448. const data = await queryTableData(params, sorter, filter);
  449. if (data !== undefined) {
  450. return Promise.resolve({
  451. data: data.rows,
  452. success: true,
  453. total: data.total,
  454. });
  455. }
  456. return Promise.resolve({
  457. data: [],
  458. success: true,
  459. });
  460. }}
  461. pagination={{
  462. defaultPageSize: defaultPageSize,
  463. showQuickJumper: true,
  464. showSizeChanger: true,
  465. onChange: pageChange,
  466. }}
  467. search={
  468. showSearch
  469. ? {
  470. defaultCollapsed: false,
  471. searchText: "搜索",
  472. }
  473. : false
  474. }
  475. dateFormatter="string"
  476. actionRef={actionTableRef}
  477. toolbar={{
  478. actions: [
  479. <ModalForm
  480. key="addmodal"
  481. title="添加字典数据"
  482. trigger={
  483. <Button icon={<PlusOutlined />} type="primary">
  484. 新建
  485. </Button>
  486. }
  487. autoFocusFirstInput
  488. modalProps={{
  489. destroyOnHidden: true,
  490. }}
  491. submitTimeout={2000}
  492. onFinish={executeAddData}
  493. >
  494. <ProForm.Group>
  495. <ProFormText
  496. width="md"
  497. name="dictType"
  498. label="字典类型"
  499. initialValue={defaultType}
  500. disabled
  501. />
  502. </ProForm.Group>
  503. <ProForm.Group>
  504. <ProFormText
  505. width="md"
  506. name="dictLabel"
  507. label="数据标签"
  508. rules={[{ required: true, message: "请输入数据标签" }]}
  509. />
  510. <ProFormText
  511. width="md"
  512. name="dictValue"
  513. label="数据键值"
  514. rules={[{ required: true, message: "请输入数据键值" }]}
  515. />
  516. </ProForm.Group>
  517. <ProForm.Group>
  518. <ProFormDigit
  519. fieldProps={{ precision: 0 }}
  520. width="md"
  521. name="dictSort"
  522. initialValue="0"
  523. label="数据排序"
  524. placeholder="请输入数据排序"
  525. rules={[{ required: true, message: "请输入数据排序" }]}
  526. />
  527. <ProFormRadio.Group
  528. width="md"
  529. name="status"
  530. label="状态"
  531. initialValue="0"
  532. options={[
  533. {
  534. label: "正常",
  535. value: "0",
  536. },
  537. {
  538. label: "停用",
  539. value: "1",
  540. },
  541. ]}
  542. />
  543. </ProForm.Group>
  544. <ProForm.Group>
  545. <ProFormSelect
  546. width="md"
  547. name="listClass"
  548. label="回显样式"
  549. valueEnum={{
  550. default: {
  551. text: "默认(default)",
  552. status: "default",
  553. },
  554. primary: {
  555. text: "主要(primary)",
  556. status: "primary",
  557. },
  558. success: {
  559. text: "成功(成功)",
  560. status: "success",
  561. },
  562. info: {
  563. text: "信息(info)",
  564. status: "info",
  565. },
  566. warning: {
  567. text: "警告(warning)",
  568. status: "warning",
  569. },
  570. danger: {
  571. text: "危险(danger)",
  572. status: "danger",
  573. },
  574. }}
  575. />
  576. <ProFormText width="md" name="cssClass" label="样式属性" />
  577. </ProForm.Group>
  578. <ProFormTextArea
  579. name="remark"
  580. width={688}
  581. label="备注"
  582. placeholder="请输入内容"
  583. />
  584. </ModalForm>,
  585. <ModalForm
  586. key="modifymodal"
  587. title="修改岗位"
  588. formRef={modifyFormRef}
  589. trigger={
  590. <Button
  591. icon={<FontAwesomeIcon icon={faPenToSquare} />}
  592. disabled={!rowCanModify}
  593. onClick={() => onClickShowRowModifyModal()}
  594. >
  595. 修改
  596. </Button>
  597. }
  598. open={isShowModifyDataModal}
  599. autoFocusFirstInput
  600. modalProps={{
  601. destroyOnHidden: true,
  602. onCancel: () => {
  603. setIsShowModifyDataModal(false);
  604. },
  605. }}
  606. submitTimeout={2000}
  607. onFinish={executeModifyData}
  608. >
  609. <ProForm.Group>
  610. <ProFormText
  611. width="md"
  612. name="dictType"
  613. label="字典类型"
  614. disabled
  615. />
  616. </ProForm.Group>
  617. <ProForm.Group>
  618. <ProFormText
  619. width="md"
  620. name="dictLabel"
  621. label="字典标签"
  622. rules={[{ required: true, message: "请输入字典标签" }]}
  623. />
  624. <ProFormText
  625. width="md"
  626. name="dictValue"
  627. label="字典键值"
  628. rules={[{ required: true, message: "请输入字典键值" }]}
  629. />
  630. </ProForm.Group>
  631. <ProForm.Group>
  632. <ProFormDigit
  633. fieldProps={{ precision: 0 }}
  634. width="md"
  635. name="dictSort"
  636. initialValue="0"
  637. label="显示排序"
  638. placeholder="请输入显示排序"
  639. rules={[{ required: true, message: "请输入显示排序" }]}
  640. />
  641. <ProFormRadio.Group
  642. width="md"
  643. name="status"
  644. label="状态"
  645. initialValue="0"
  646. options={[
  647. {
  648. label: "正常",
  649. value: "0",
  650. },
  651. {
  652. label: "停用",
  653. value: "1",
  654. },
  655. ]}
  656. />
  657. </ProForm.Group>
  658. <ProForm.Group>
  659. <ProFormSelect
  660. width="md"
  661. name="listClass"
  662. label="回显样式"
  663. valueEnum={{
  664. default: {
  665. text: "默认(default)",
  666. status: "default",
  667. },
  668. primary: {
  669. text: "主要(primary)",
  670. status: "primary",
  671. },
  672. success: {
  673. text: "成功(成功)",
  674. status: "success",
  675. },
  676. info: {
  677. text: "信息(info)",
  678. status: "info",
  679. },
  680. warning: {
  681. text: "警告(warning)",
  682. status: "warning",
  683. },
  684. danger: {
  685. text: "危险(danger)",
  686. status: "danger",
  687. },
  688. }}
  689. />
  690. <ProFormText width="md" name="cssClass" label="样式属性" />
  691. </ProForm.Group>
  692. <ProFormTextArea
  693. name="remark"
  694. width={688}
  695. label="备注"
  696. placeholder="请输入内容"
  697. />
  698. </ModalForm>,
  699. <Button
  700. key="danger"
  701. danger
  702. icon={<DeleteOutlined />}
  703. disabled={!rowCanDelete}
  704. onClick={() => onClickDeleteRow()}
  705. >
  706. 删除
  707. </Button>,
  708. <Button
  709. key="export"
  710. type="primary"
  711. icon={<FontAwesomeIcon icon={faDownload} />}
  712. onClick={exportTable}
  713. >
  714. 导出
  715. </Button>,
  716. ],
  717. settings: [
  718. {
  719. key: "switch",
  720. icon: showSearch ? (
  721. <FontAwesomeIcon icon={faToggleOn} />
  722. ) : (
  723. <FontAwesomeIcon icon={faToggleOff} />
  724. ),
  725. tooltip: showSearch ? "隐藏搜索栏" : "显示搜索栏",
  726. onClick: (key: string | undefined) => {
  727. setShowSearch(!showSearch);
  728. },
  729. },
  730. {
  731. key: "refresh",
  732. tooltip: "刷新",
  733. icon: <ReloadOutlined />,
  734. onClick: (key: string | undefined) => {
  735. if (actionTableRef.current) {
  736. actionTableRef.current.reload();
  737. }
  738. },
  739. },
  740. ],
  741. }}
  742. />
  743. {/* 删除确认模态框 */}
  744. <Modal
  745. title={
  746. <div style={{ display: 'flex', alignItems: 'center' }}>
  747. <ExclamationCircleFilled style={{ color: '#faad14', marginRight: 8 }} />
  748. <span>系统提示</span>
  749. </div>
  750. }
  751. open={deleteModalVisible}
  752. onOk={executeDeleteRow}
  753. onCancel={() => {
  754. setDeleteModalVisible(false);
  755. setDeleteDictCode(null);
  756. }}
  757. okText="确认"
  758. cancelText="取消"
  759. >
  760. <p>{`确定删除字典编码为“${deleteDictCode}”的数据项?`}</p>
  761. </Modal>
  762. </PageContainer>
  763. );
  764. }